#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
布局画布事件处理模块
提供LayoutCanvas的事件处理功能
"""

from PyQt5.QtCore import Qt, QRect, QRectF, QPoint, QPointF

class LayoutCanvasHandlers:
    """布局画布事件处理类"""
    
    def __init__(self, canvas):
        """初始化
        
        参数:
            canvas: LayoutCanvas实例
        """
        self.canvas = canvas
    
    def handle_mouse_press(self, event):
        """处理鼠标按下事件"""
        if not self.canvas.root:  # 无布局时不处理
            return
        
        # 处理中键按下 - 开始平移
        if event.button() == Qt.MiddleButton:
            self.canvas.panning = True
            self.canvas.pan_start_pos = event.pos()
            self.canvas.setCursor(Qt.ClosedHandCursor)  # 设置手型光标
            event.accept()  # 确保事件被接受
            return
        
        # 处理右键点击 - 恢复元素原始比例
        if event.button() == Qt.RightButton and self.canvas.selected_element:
            # 保存操作前的状态到撤销栈
            if hasattr(self.canvas, 'undo_stack'):
                for prop in self.canvas.selected_element.findall('Property'):
                    if prop.get('Name') == 'UnifiedAreaRect':
                        self.canvas.undo_stack.append({
                            'element': self.canvas.selected_element,
                            'property': 'UnifiedAreaRect',
                            'value': prop.get('Value')
                        })
                        # 限制撤销栈大小
                        if len(self.canvas.undo_stack) > self.canvas.max_undo_steps:
                            self.canvas.undo_stack.pop(0)
            
            self.restore_element_original_ratio()
            return
        
        # 获取鼠标在画布上的位置
        canvas_pos = event.pos()
        # 记录鼠标按下位置（用于判断是点击还是拖动）
        self.canvas.mouse_press_pos = canvas_pos
        
        # 计算预览区域
        canvas_width = self.canvas.width()
        canvas_height = self.canvas.height()
        scaled_width = self.canvas.resolution[0] * self.canvas.scale_factor
        scaled_height = self.canvas.resolution[1] * self.canvas.scale_factor
        x_offset = (canvas_width - scaled_width) / 2 + self.canvas.pan_offset.x()
        y_offset = (canvas_height - scaled_height) / 2 + self.canvas.pan_offset.y()
        preview_rect = QRectF(x_offset, y_offset, scaled_width, scaled_height)
        
        # 检查鼠标是否在预览区域内
        if not preview_rect.contains(QPointF(canvas_pos)):
            return
        
        # 将鼠标位置转换为布局坐标，使用浮点值保持精度
        layout_x = (canvas_pos.x() - x_offset) / self.canvas.scale_factor
        layout_y = (canvas_pos.y() - y_offset) / self.canvas.scale_factor
        layout_pos = QPointF(layout_x, layout_y)
        
        # 如果已有选中元素，首先检查是否点击了调整手柄 (优先级更高)
        if self.canvas.selected_element:
            handle = None
            element_rect = None
            
            # 获取选中元素的矩形
            parent_element = self.canvas.utils.find_parent_element(self.canvas.selected_element)
            if parent_element:
                parent_rect = self.canvas.utils.parse_area_rect(parent_element, QRect(0, 0, self.canvas.resolution[0], self.canvas.resolution[1]))
                if parent_rect:
                    element_rect = self.canvas.utils.parse_area_rect(self.canvas.selected_element, parent_rect)
                    if element_rect:
                        # 检查是否点击了调整手柄 - 增加手柄检测的优先级
                        handle = self.canvas.utils.get_handle_at_position(layout_pos, element_rect)
            # 如果没有父元素，说明可能是根元素
            elif self.canvas.selected_element == self.canvas.root or (self.canvas.root.tag == 'GUILayout' and self.canvas.selected_element == self.canvas.root.find('Window')):
                element_rect = self.canvas.utils.parse_area_rect(self.canvas.selected_element, QRect(0, 0, self.canvas.resolution[0], self.canvas.resolution[1]))
                if element_rect:
                    # 检查是否点击了调整手柄
                    handle = self.canvas.utils.get_handle_at_position(layout_pos, element_rect)
                    parent_rect = QRect(0, 0, self.canvas.resolution[0], self.canvas.resolution[1])
            
            # 如果点击了调整手柄，设置调整大小模式
            if handle is not None and element_rect:
                # 保存操作前的状态到撤销栈
                if hasattr(self.canvas, 'undo_stack'):
                    for prop in self.canvas.selected_element.findall('Property'):
                        if prop.get('Name') == 'UnifiedAreaRect':
                            self.canvas.undo_stack.append({
                                'element': self.canvas.selected_element,
                                'property': 'UnifiedAreaRect',
                                'value': prop.get('Value')
                            })
                            # 限制撤销栈大小
                            if len(self.canvas.undo_stack) > self.canvas.max_undo_steps:
                                self.canvas.undo_stack.pop(0)
                
                # 设置调整大小模式
                self.canvas.resizing = True
                self.canvas.resize_element = self.canvas.selected_element
                self.canvas.resize_handle = handle
                self.canvas.resize_start_pos = layout_pos
                self.canvas.resize_start_rect = element_rect
                if parent_element:
                    self.canvas.cached_parent_rect = parent_rect
                else:
                    self.canvas.cached_parent_rect = QRect(0, 0, self.canvas.resolution[0], self.canvas.resolution[1])
                self.canvas.potential_select_element = None  # 清除潜在选中元素
                
                # 设置适当的光标
                self.canvas.utils.update_cursor_for_handle(handle)
                
                # 阻止事件进一步传播
                event.accept()
                return
                
            # 如果没有点击手柄，但点击在了元素内部，准备拖动该元素
            if element_rect and element_rect.contains(int(layout_pos.x()), int(layout_pos.y())):
                # 点击了当前选中元素，准备拖动该元素
                element = self.canvas.selected_element
                
                # 保存操作前的状态到撤销栈
                if hasattr(self.canvas, 'undo_stack'):
                    for prop in element.findall('Property'):
                        if prop.get('Name') == 'UnifiedAreaRect':
                            self.canvas.undo_stack.append({
                                'element': element,
                                'property': 'UnifiedAreaRect',
                                'value': prop.get('Value')
                            })
                            # 限制撤销栈大小
                            if len(self.canvas.undo_stack) > self.canvas.max_undo_steps:
                                self.canvas.undo_stack.pop(0)
                
                # 设置拖拽状态
                self.canvas.dragging = True
                self.canvas.drag_element = element
                self.canvas.drag_start_pos = layout_pos
                self.canvas.drag_start_rect = element_rect
                
                if parent_element:
                    self.canvas.cached_parent_rect = parent_rect
                else:
                    self.canvas.cached_parent_rect = QRect(0, 0, self.canvas.resolution[0], self.canvas.resolution[1])
                
                self.canvas.potential_select_element = None  # 清除潜在选中元素
                self.canvas.setCursor(Qt.SizeAllCursor)  # 设置拖动光标
                
                # 阻止事件进一步传播
                event.accept()
                return
        
        # 如果没有点击到当前选中元素的手柄或元素本身，寻找新的元素
        # 查找鼠标位置的元素
        found_element = self.canvas.utils.find_element_at_position(layout_pos)
        
        # 如果找到元素，则选中它
        if found_element:
            # 设置为潜在选中元素，只有在鼠标释放时且没有发生拖动时才真正选中
            self.canvas.potential_select_element = found_element
        else:
            # 如果没有找到元素，也清除选中状态，但只在鼠标释放时执行
            self.canvas.potential_select_element = None
    
    def handle_mouse_move(self, event):
        """处理鼠标移动事件"""
        # 保存鼠标位置用于手柄悬停效果
        canvas_pos = event.pos()
        
        # 计算预览区域
        canvas_width = self.canvas.width()
        canvas_height = self.canvas.height()
        scaled_width = self.canvas.resolution[0] * self.canvas.scale_factor
        scaled_height = self.canvas.resolution[1] * self.canvas.scale_factor
        x_offset = (canvas_width - scaled_width) / 2 + self.canvas.pan_offset.x()
        y_offset = (canvas_height - scaled_height) / 2 + self.canvas.pan_offset.y()
        
        # 计算鼠标在布局坐标中的位置
        preview_rect = QRectF(x_offset, y_offset, scaled_width, scaled_height)
        
        if preview_rect.contains(QPointF(canvas_pos)):
            layout_x = (canvas_pos.x() - x_offset) / self.canvas.scale_factor
            layout_y = (canvas_pos.y() - y_offset) / self.canvas.scale_factor
            self.canvas.last_mouse_pos = QPointF(layout_x, layout_y)
        else:
            self.canvas.last_mouse_pos = None
            
        # 如果正在平移
        if self.canvas.panning and self.canvas.pan_start_pos:
            # 计算移动距离
            delta = canvas_pos - self.canvas.pan_start_pos
            
            # 更新平移偏移量
            self.canvas.pan_offset += delta
            
            # 更新开始平移位置
            self.canvas.pan_start_pos = canvas_pos
            
            # 更新界面
            self.canvas.update()
            
            # 确保事件被接受
            event.accept()
            return
            
        # 如果正在调整大小
        if self.canvas.resizing and self.canvas.resize_element and self.canvas.resize_start_pos and self.canvas.resize_start_rect:
            # 性能优化: 检查更新间隔
            current_time = event.timestamp()
            if self.canvas.last_update_time > 0 and current_time - self.canvas.last_update_time < self.canvas.update_interval:
                return  # 如果距离上次更新的时间太短，跳过本次更新
            
            # 记录本次更新时间
            self.canvas.last_update_time = current_time
            
            preview_rect = QRectF(x_offset, y_offset, scaled_width, scaled_height)
            
            # 检查鼠标是否在预览区域内
            if not preview_rect.contains(QPointF(canvas_pos)):
                return
            
            # 将鼠标位置转换为布局坐标，使用浮点值保持精度
            layout_x = (canvas_pos.x() - x_offset) / self.canvas.scale_factor
            layout_y = (canvas_pos.y() - y_offset) / self.canvas.scale_factor
            layout_pos = QPointF(layout_x, layout_y)
            
            # 计算鼠标移动距离
            delta_x = layout_pos.x() - self.canvas.resize_start_pos.x()
            delta_y = layout_pos.y() - self.canvas.resize_start_pos.y()
            
            # 获取原始矩形的属性
            orig_x = self.canvas.resize_start_rect.x()
            orig_y = self.canvas.resize_start_rect.y()
            orig_width = self.canvas.resize_start_rect.width()
            orig_height = self.canvas.resize_start_rect.height()
            
            # 根据激活的手柄计算新的位置和大小
            new_x = orig_x
            new_y = orig_y
            new_width = orig_width
            new_height = orig_height
            
            # 计算原始比例
            aspect_ratio = orig_width / orig_height if orig_height != 0 else 1.0
            
            # 根据手柄位置调整大小
            if self.canvas.resize_handle == self.canvas.resize_handle_positions['top_left']:  # 左上
                if self.canvas.alt_pressed:
                    # 保持比例
                    if abs(delta_x) > abs(delta_y):
                        # 以水平方向为主
                        delta_y = delta_x / aspect_ratio
                    else:
                        # 以垂直方向为主
                        delta_x = delta_y * aspect_ratio
                new_x = orig_x + delta_x
                new_y = orig_y + delta_y
                new_width = orig_width - delta_x
                new_height = orig_height - delta_y
            
            elif self.canvas.resize_handle == self.canvas.resize_handle_positions['top']:  # 上
                new_y = orig_y + delta_y
                new_height = orig_height - delta_y
            
            elif self.canvas.resize_handle == self.canvas.resize_handle_positions['top_right']:  # 右上
                if self.canvas.alt_pressed:
                    # 保持比例
                    if abs(delta_x) > abs(delta_y):
                        # 以水平方向为主
                        delta_y = -delta_x / aspect_ratio
                    else:
                        # 以垂直方向为主
                        delta_x = -delta_y * aspect_ratio
                new_y = orig_y + delta_y
                new_width = orig_width + delta_x
                new_height = orig_height - delta_y
            
            elif self.canvas.resize_handle == self.canvas.resize_handle_positions['right']:  # 右
                new_width = orig_width + delta_x
            
            elif self.canvas.resize_handle == self.canvas.resize_handle_positions['bottom_right']:  # 右下
                if self.canvas.alt_pressed:
                    # 保持比例
                    if abs(delta_x) > abs(delta_y):
                        # 以水平方向为主
                        delta_y = delta_x / aspect_ratio
                    else:
                        # 以垂直方向为主
                        delta_x = delta_y * aspect_ratio
                new_width = orig_width + delta_x
                new_height = orig_height + delta_y
            
            elif self.canvas.resize_handle == self.canvas.resize_handle_positions['bottom']:  # 下
                new_height = orig_height + delta_y
            
            elif self.canvas.resize_handle == self.canvas.resize_handle_positions['bottom_left']:  # 左下
                if self.canvas.alt_pressed:
                    # 保持比例
                    if abs(delta_x) > abs(delta_y):
                        # 以水平方向为主
                        delta_y = -delta_x / aspect_ratio
                    else:
                        # 以垂直方向为主
                        delta_x = -delta_y * aspect_ratio
                new_x = orig_x + delta_x
                new_width = orig_width - delta_x
                new_height = orig_height + delta_y
            
            elif self.canvas.resize_handle == self.canvas.resize_handle_positions['left']:  # 左
                new_x = orig_x + delta_x
                new_width = orig_width - delta_x
            
            # 确保宽度和高度不小于最小值
            min_size = 10
            if new_width < min_size:
                if self.canvas.resize_handle in [self.canvas.resize_handle_positions['left'], self.canvas.resize_handle_positions['top_left'], self.canvas.resize_handle_positions['bottom_left']]:
                    new_x = orig_x + orig_width - min_size
                new_width = min_size
            
            if new_height < min_size:
                if self.canvas.resize_handle in [self.canvas.resize_handle_positions['top'], self.canvas.resize_handle_positions['top_left'], self.canvas.resize_handle_positions['top_right']]:
                    new_y = orig_y + orig_height - min_size
                new_height = min_size
            
            # 更新元素位置
            if self.canvas.cached_parent_rect:
                self.canvas.utils.update_element_position_optimized(
                    self.canvas.resize_element, 
                    self.canvas.cached_parent_rect, 
                    new_x, 
                    new_y, 
                    new_width, 
                    new_height
                )
                
                # 更新界面
                self.canvas.update()
            
            return
        
        # 处理普通拖动
        if self.canvas.dragging and self.canvas.drag_element and self.canvas.drag_start_pos and self.canvas.drag_start_rect and self.canvas.cached_parent_rect:
            # 性能优化: 检查更新间隔
            current_time = event.timestamp()
            if self.canvas.last_update_time > 0 and current_time - self.canvas.last_update_time < self.canvas.update_interval:
                return  # 如果距离上次更新的时间太短，跳过本次更新
            
            # 记录本次更新时间
            self.canvas.last_update_time = current_time
            
            preview_rect = QRect(int(x_offset), int(y_offset), int(scaled_width), int(scaled_height))
            
            # 检查鼠标是否在预览区域内
            if not preview_rect.contains(canvas_pos):
                return
            
            # 将鼠标位置转换为布局坐标
            layout_x = (canvas_pos.x() - x_offset) / self.canvas.scale_factor
            layout_y = (canvas_pos.y() - y_offset) / self.canvas.scale_factor
            layout_pos = QPoint(int(layout_x), int(layout_y))
            
            # 计算鼠标移动距离
            delta_x = layout_pos.x() - self.canvas.drag_start_pos.x()
            delta_y = layout_pos.y() - self.canvas.drag_start_pos.y()
            
            # 计算新位置
            new_x = self.canvas.drag_start_rect.x() + delta_x
            new_y = self.canvas.drag_start_rect.y() + delta_y
            
            # 更新元素位置
            self.canvas.utils.update_element_position_optimized(
                self.canvas.drag_element,
                self.canvas.cached_parent_rect,
                new_x,
                new_y,
                self.canvas.drag_start_rect.width(),
                self.canvas.drag_start_rect.height()
            )
            
            # 更新界面
            self.canvas.update()
            
            return
            
        # 如果不在拖动状态，且有选中元素，检查鼠标是否在调整手柄上，更新光标
        if self.canvas.selected_element:
            # 获取鼠标在画布上的位置
            canvas_pos = event.pos()
            
            # 计算预览区域
            canvas_width = self.canvas.width()
            canvas_height = self.canvas.height()
            scaled_width = self.canvas.resolution[0] * self.canvas.scale_factor
            scaled_height = self.canvas.resolution[1] * self.canvas.scale_factor
            x_offset = (canvas_width - scaled_width) / 2 + self.canvas.pan_offset.x()
            y_offset = (canvas_height - scaled_height) / 2 + self.canvas.pan_offset.y()
            
            # 检查鼠标是否在预览区域内
            preview_rect = QRect(int(x_offset), int(y_offset), int(scaled_width), int(scaled_height))
            if not preview_rect.contains(canvas_pos):
                self.canvas.setCursor(Qt.ArrowCursor)
                return
            
            # 将鼠标位置转换为布局坐标
            layout_x = (canvas_pos.x() - x_offset) / self.canvas.scale_factor
            layout_y = (canvas_pos.y() - y_offset) / self.canvas.scale_factor
            layout_pos = QPoint(int(layout_x), int(layout_y))
            
            # 获取选中元素的矩形
            parent_element = self.canvas.utils.find_parent_element(self.canvas.selected_element)
            if parent_element:
                parent_rect = self.canvas.utils.parse_area_rect(parent_element, QRect(0, 0, self.canvas.resolution[0], self.canvas.resolution[1]))
                if parent_rect:
                    element_rect = self.canvas.utils.parse_area_rect(self.canvas.selected_element, parent_rect)
                    if element_rect:
                        # 检查鼠标是否在调整手柄上，更新光标
                        handle = self.canvas.utils.get_handle_at_position(layout_pos, element_rect)
                        self.canvas.utils.update_cursor_for_handle(handle)
                        
                        # 如果不是在手柄上，恢复默认光标
                        if handle is None:
                            self.canvas.setCursor(Qt.ArrowCursor)
                            
                            # 检查是否在元素内部
                            if element_rect.contains(int(layout_pos.x()), int(layout_pos.y())):
                                self.canvas.setCursor(Qt.SizeAllCursor)  # 可拖动的光标
        
        # 如果不在拖动和调整大小状态，更新潜在选择元素
        if not self.canvas.dragging and not self.canvas.resizing and preview_rect.contains(canvas_pos):
            # 将鼠标位置转换为布局坐标
            layout_x = (canvas_pos.x() - x_offset) / self.canvas.scale_factor
            layout_y = (canvas_pos.y() - y_offset) / self.canvas.scale_factor
            layout_pos = QPointF(layout_x, layout_y)
            
            # 查找鼠标位置的元素
            found_element = self.canvas.utils.find_element_at_position(layout_pos)
            
            # 如果找到元素，记录为潜在选中元素
            self.canvas.potential_select_element = found_element
            
            # 更新界面以显示悬停效果
            self.canvas.update()
    
    def handle_mouse_release(self, event):
        """处理鼠标释放事件"""
        # 处理鼠标中键释放 - 结束平移
        if event.button() == Qt.MiddleButton and self.canvas.panning:
            self.canvas.panning = False
            self.canvas.setCursor(Qt.ArrowCursor)  # 恢复箭头光标
            event.accept()
            return
            
        # 如果是调整大小结束
        if self.canvas.resizing and self.canvas.resize_element:
            # 保存操作到撤销栈
            if hasattr(self.canvas, 'undo_stack'):
                # 深拷贝当前元素的UnifiedAreaRect属性
                for prop in self.canvas.resize_element.findall('Property'):
                    if prop.get('Name') == 'UnifiedAreaRect':
                        self.canvas.undo_stack.append({
                            'element': self.canvas.resize_element,
                            'property': 'UnifiedAreaRect',
                            'value': prop.get('Value')
                        })
                        # 限制撤销栈大小
                        if len(self.canvas.undo_stack) > self.canvas.max_undo_steps:
                            self.canvas.undo_stack.pop(0)
            
            self.canvas.resizing = False
            self.canvas.resize_handle = None
            self.canvas.resize_start_pos = None
            self.canvas.resize_start_rect = None
            
            # 通知主窗口布局已被修改
            if hasattr(self.canvas.parent(), 'is_layout_modified'):
                self.canvas.parent().is_layout_modified = True
                self.canvas.parent().update_window_title()
            
            # 清除缓存
            self.canvas.cached_parent_rect = None
            
            # 完整更新一次界面
            self.canvas.update()
            
            return
        
        # 判断鼠标是否有明显移动（拖动vs点击）
        is_click = False
        if self.canvas.mouse_press_pos:
            current_pos = event.pos()
            dx = current_pos.x() - self.canvas.mouse_press_pos.x()
            dy = current_pos.y() - self.canvas.mouse_press_pos.y()
            distance = (dx*dx + dy*dy) ** 0.5  # 计算欧几里得距离
            
            # 如果移动距离小于拖动阈值，视为点击
            if distance < self.canvas.drag_threshold:
                is_click = True
        
        # 如果是拖拽结束
        if self.canvas.dragging:
            # 保存操作到撤销栈
            if hasattr(self.canvas, 'undo_stack') and self.canvas.drag_element:
                # 深拷贝当前元素的UnifiedAreaRect属性
                for prop in self.canvas.drag_element.findall('Property'):
                    if prop.get('Name') == 'UnifiedAreaRect':
                        self.canvas.undo_stack.append({
                            'element': self.canvas.drag_element,
                            'property': 'UnifiedAreaRect',
                            'value': prop.get('Value')
                        })
                        # 限制撤销栈大小
                        if len(self.canvas.undo_stack) > self.canvas.max_undo_steps:
                            self.canvas.undo_stack.pop(0)
            
            # 如果是点击而不是拖动，且有潜在选中的元素，则真正选中该元素
            if is_click and self.canvas.potential_select_element:
                # 使用新的选中元素方法，会触发元素选择信号
                self.canvas.set_selected_element(self.canvas.potential_select_element)
            
            # 通知主窗口布局已被修改
            if hasattr(self.canvas.parent(), 'is_layout_modified'):
                self.canvas.parent().is_layout_modified = True
                self.canvas.parent().update_window_title()
            
            # 重置状态
            self.canvas.dragging = False
            self.canvas.drag_start_pos = None
            self.canvas.drag_start_rect = None
            self.canvas.cached_parent_rect = None  # 清除缓存
            
            # 释放拖动后执行一次完整更新
            self.canvas.update()
            
            # 清除选择相关变量
            self.canvas.potential_select_element = None
            self.canvas.mouse_press_pos = None
            
            return
        
        # 处理普通点击选择
        if is_click:
            # 获取鼠标在画布上的位置
            canvas_pos = event.pos()
            
            # 计算预览区域
            canvas_width = self.canvas.width()
            canvas_height = self.canvas.height()
            scaled_width = self.canvas.resolution[0] * self.canvas.scale_factor
            scaled_height = self.canvas.resolution[1] * self.canvas.scale_factor
            x_offset = (canvas_width - scaled_width) / 2 + self.canvas.pan_offset.x()
            y_offset = (canvas_height - scaled_height) / 2 + self.canvas.pan_offset.y()
            preview_rect = QRect(int(x_offset), int(y_offset), int(scaled_width), int(scaled_height))
            
            # 检查鼠标是否在预览区域内
            if preview_rect.contains(canvas_pos):
                # 将鼠标位置转换为布局坐标
                layout_x = (canvas_pos.x() - x_offset) / self.canvas.scale_factor
                layout_y = (canvas_pos.y() - y_offset) / self.canvas.scale_factor
                layout_pos = QPointF(layout_x, layout_y)
                
                # 如果有潜在选中元素，选中它
                if self.canvas.potential_select_element:
                    self.canvas.set_selected_element(self.canvas.potential_select_element)
                else:
                    # 如果点击在空白区域，取消当前选中
                    if self.canvas.selected_element:
                        self.canvas.set_selected_element(None)
            else:
                # 如果点击在预览区域外，也取消当前选中
                if self.canvas.selected_element:
                    self.canvas.set_selected_element(None)
        
        # 清除选择相关变量
        self.canvas.potential_select_element = None
        self.canvas.mouse_press_pos = None
    
    def handle_key_press(self, event):
        """处理键盘按下事件"""
        if event.key() == Qt.Key_Alt:
            self.canvas.alt_pressed = True
            # 如果正在调整大小，更新视图
            if self.canvas.resizing:
                self.canvas.update()
        elif event.key() == Qt.Key_Control:
            self.canvas.ctrl_pressed = True
        
        # 处理撤销操作 (Ctrl+Z)
        if self.canvas.ctrl_pressed and event.key() == Qt.Key_Z:
            self.undo_last_action()
        
        super(self.canvas.__class__, self.canvas).keyPressEvent(event)
    
    def handle_key_release(self, event):
        """处理键盘释放事件"""
        if event.key() == Qt.Key_Alt:
            self.canvas.alt_pressed = False
            # 如果正在调整大小，更新视图
            if self.canvas.resizing:
                self.canvas.update()
        elif event.key() == Qt.Key_Control:
            self.canvas.ctrl_pressed = False
        super(self.canvas.__class__, self.canvas).keyReleaseEvent(event)
    
    def handle_wheel(self, event):
        """处理鼠标滚轮事件，实现缩放功能"""
        # 获取滚轮角度增量，Qt中通常为120的倍数
        delta = event.angleDelta().y()
        
        # 缩放比例调整步长
        zoom_factor = 0.1
        
        # 计算新的缩放系数
        if delta > 0:
            # 向上滚动，放大
            self.canvas.scale_factor = min(3.0, self.canvas.scale_factor + zoom_factor)
        else:
            # 向下滚动，缩小
            self.canvas.scale_factor = max(0.2, self.canvas.scale_factor - zoom_factor)
        
        # 更新界面
        self.canvas.update()
        
        # 发送事件已被处理的信息
        event.accept()
    
    def undo_last_action(self):
        """撤销上一步操作"""
        if not self.canvas.undo_stack:
            # 撤销栈为空，无法撤销
            return
        
        # 获取最后一个操作
        last_action = self.canvas.undo_stack.pop()
        
        # 还原属性值
        element = last_action.get('element')
        prop_name = last_action.get('property')
        prop_value = last_action.get('value')
        
        if element is not None and prop_name and prop_value:
            for prop in element.findall('Property'):
                if prop.get('Name') == prop_name:
                    prop.set('Value', prop_value)
                    break
            
            # 通知主窗口布局已被修改
            if hasattr(self.canvas.parent(), 'is_layout_modified'):
                self.canvas.parent().is_layout_modified = True
                self.canvas.parent().update_window_title()
            
            # 更新视图
            self.canvas.update()
    
    def restore_element_original_ratio(self):
        """恢复元素原始比例（从图集中获取）"""
        if not self.canvas.selected_element:
            return
            
        # 检查元素类型，只有StaticImage和Button类型的元素需要恢复比例
        element_type = self.canvas.selected_element.get('Type', '')
        if 'StaticImage' not in element_type and 'Button' not in element_type:
            return
            
        # 查找图像属性
        image_prop = None
        
        # 根据元素类型选择图像属性
        if 'Button' in element_type:
            # 对于按钮，优先使用正常状态图像
            for prop in self.canvas.selected_element.findall('Property'):
                if prop.get('Name') == 'olNormalImage':
                    image_prop = prop.get('Value')
                    break
        
        # 如果没有找到特定状态图像，使用Image属性
        if not image_prop:
            for prop in self.canvas.selected_element.findall('Property'):
                if prop.get('Name') == 'Image':
                    image_prop = prop.get('Value')
                    break
        
        # 如果仍然没有找到图像属性，检查其他常见图像属性
        if not image_prop:
            image_prop_names = [
                'olNormalImage', 'olHoverImage', 'olPushedImage', 
                'olDisabledImage', 'olSelectedImage', 'olHighlightImage'
            ]
            for prop_name in image_prop_names:
                for prop in self.canvas.selected_element.findall('Property'):
                    if prop.get('Name') == prop_name:
                        image_prop = prop.get('Value')
                        break
                if image_prop:
                    break
        
        # 如果没有找到图像属性，无法恢复比例
        if not image_prop:
            print("未找到图像属性，无法恢复原始比例")
            return
            
        # 解析图像属性，格式为 "set:imageset_name image:image_name"
        try:
            # 支持"set:图集名 image:图片名"格式
            set_part = None
            image_part = None
            
            # 分开解析set和image部分
            parts = image_prop.split()
            for part in parts:
                if part.startswith("set:"):
                    set_part = part[4:]  # 去掉"set:"前缀
                elif part.startswith("image:"):
                    image_part = part[6:]  # 去掉"image:"前缀
            
            if not set_part or not image_part:
                print(f"无效的图像属性格式: {image_prop}")
                return
            
            imageset_name = set_part
            image_name = image_part
            
            # 获取图像信息
            img_info = self.canvas.main_window.xml_handler.get_image_info(imageset_name, image_name)
            if not img_info:
                print(f"未找到图集 {imageset_name} 中的图像 {image_name}")
                return
                
            # 获取图像原始尺寸
            orig_width = img_info['Width']
            orig_height = img_info['Height']
            
            # 获取元素的父元素和当前尺寸
            parent_element = self.canvas.utils.find_parent_element(self.canvas.selected_element)
            if not parent_element:
                print("未找到父元素")
                return
                
            parent_rect = self.canvas.utils.parse_area_rect(parent_element, QRect(0, 0, self.canvas.resolution[0], self.canvas.resolution[1]))
            if not parent_rect:
                print("无法解析父元素区域")
                return
                
            element_rect = self.canvas.utils.parse_area_rect(self.canvas.selected_element, parent_rect)
            if not element_rect:
                print("无法解析元素区域")
                return
                
            # 计算新的宽度和高度，保持图像原始比例
            current_width = element_rect.width()
            current_height = element_rect.height()
            
            # 获取当前左上角坐标
            current_x = element_rect.x()
            current_y = element_rect.y()
            
            # 根据原始比例计算新尺寸
            aspect_ratio = orig_width / orig_height
            
            # 使用当前宽度，按比例计算高度
            new_height = int(current_width / aspect_ratio)
            
            # 更新元素位置，保持左上角不变
            self.canvas.utils.update_element_position_optimized(
                self.canvas.selected_element, 
                parent_rect, 
                current_x, 
                current_y, 
                current_width, 
                new_height
            )
            
            # 更新界面
            self.canvas.update()
            
            # 通知主窗口布局已被修改
            if hasattr(self.canvas.parent(), 'is_layout_modified'):
                self.canvas.parent().is_layout_modified = True
                self.canvas.parent().update_window_title()
                
            print(f"已恢复元素 {self.canvas.selected_element.get('Name', '未命名')} 的原始比例: {orig_width}x{orig_height}")
            
        except Exception as e:
            print(f"恢复原始比例时出错: {e}")
    
    def find_and_select_tree_item(self, item, element):
        """递归查找并选中树项"""
        # 检查当前项
        if item.data(0, Qt.UserRole) == element:
            item.setSelected(True)
            self.canvas.parent().element_tree.setCurrentItem(item)
            return True
        
        # 检查子项
        for i in range(item.childCount()):
            child = item.child(i)
            if self.find_and_select_tree_item(child, element):
                return True 